home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / share / pyshared / serial / serialposix.py < prev    next >
Text File  |  2008-06-25  |  17KB  |  452 lines

  1. #! /usr/bin/python
  2. #Python Serial Port Extension for Win32, Linux, BSD, Jython
  3. #module for serial IO for POSIX compatible systems, like Linux
  4. #see __init__.py
  5. #
  6. #(C) 2001-2003 Chris Liechti <cliechti@gmx.net>
  7. # this is distributed under a free software license, see license.txt
  8. #
  9. #parts based on code from Grant B. Edwards  <grante@visi.com>:
  10. #  ftp://ftp.visi.com/users/grante/python/PosixSerial.py
  11. # references: http://www.easysw.com/~mike/serial/serial.html
  12.  
  13. import sys, os, fcntl, termios, struct, select, errno
  14. from serialutil import *
  15.  
  16. VERSION = "$Revision: 1.35 $".split()[1]     #extract CVS version
  17.  
  18. #Do check the Python version as some constants have moved.
  19. if (sys.hexversion < 0x020100f0):
  20.     import TERMIOS
  21. else:
  22.     TERMIOS = termios
  23.  
  24. if (sys.hexversion < 0x020200f0):
  25.     import FCNTL
  26. else:
  27.     FCNTL = fcntl
  28.  
  29. #try to detect the os so that a device can be selected...
  30. plat = sys.platform.lower()
  31.  
  32. if   plat[:5] == 'linux':    #Linux (confirmed)
  33.     def device(port):
  34.         return '/dev/ttyS%d' % port
  35.  
  36. elif plat == 'cygwin':       #cywin/win32 (confirmed)
  37.     def device(port):
  38.         return '/dev/com%d' % (port + 1)
  39.  
  40. elif plat     == 'openbsd3': #BSD (confirmed)
  41.     def device(port):
  42.         return '/dev/ttyp%d' % port
  43.  
  44. elif plat[:3] == 'bsd' or  \
  45.      plat[:7] == 'freebsd' or \
  46.      plat[:7] == 'openbsd' or \
  47.      plat[:6] == 'darwin':   #BSD (confirmed for freebsd4: cuaa%d)
  48.     def device(port):
  49.         return '/dev/cuad%d' % port
  50.  
  51. elif plat[:6] == 'netbsd':   #NetBSD 1.6 testing by Erk
  52.     def device(port):
  53.         return '/dev/dty%02d' % port
  54.  
  55. elif plat[:4] == 'irix':     #IRIX (partialy tested)
  56.     def device(port):
  57.         return '/dev/ttyf%d' % (port+1) #XXX different device names depending on flow control
  58.  
  59. elif plat[:2] == 'hp':       #HP-UX (not tested)
  60.     def device(port):
  61.         return '/dev/tty%dp0' % (port+1)
  62.  
  63. elif plat[:5] == 'sunos':    #Solaris/SunOS (confirmed)
  64.     def device(port):
  65.         return '/dev/tty%c' % (ord('a')+port)
  66.         
  67. elif plat[:3] == 'aix':      #aix
  68.     def device(port):
  69.         return '/dev/tty%d' % (port)
  70.  
  71. else:
  72.     #platform detection has failed...
  73.     print """don't know how to number ttys on this system.
  74. ! Use an explicit path (eg /dev/ttyS1) or send this information to
  75. ! the author of this module:
  76.  
  77. sys.platform = %r
  78. os.name = %r
  79. serialposix.py version = %s
  80.  
  81. also add the device name of the serial port and where the
  82. counting starts for the first serial port.
  83. e.g. 'first serial port: /dev/ttyS0'
  84. and with a bit luck you can get this module running...
  85. """ % (sys.platform, os.name, VERSION)
  86.     #no exception, just continue with a brave attempt to build a device name
  87.     #even if the device name is not correct for the platform it has chances
  88.     #to work using a string with the real device name as port paramter.
  89.     def device(portum):
  90.         return '/dev/ttyS%d' % portnum
  91.     #~ raise Exception, "this module does not run on this platform, sorry."
  92.  
  93. #whats up with "aix", "beos", ....
  94. #they should work, just need to know the device names.
  95.  
  96.  
  97. #load some constants for later use.
  98. #try to use values from TERMIOS, use defaults from linux otherwise
  99. TIOCMGET  = hasattr(TERMIOS, 'TIOCMGET') and TERMIOS.TIOCMGET or 0x5415
  100. TIOCMBIS  = hasattr(TERMIOS, 'TIOCMBIS') and TERMIOS.TIOCMBIS or 0x5416
  101. TIOCMBIC  = hasattr(TERMIOS, 'TIOCMBIC') and TERMIOS.TIOCMBIC or 0x5417
  102. TIOCMSET  = hasattr(TERMIOS, 'TIOCMSET') and TERMIOS.TIOCMSET or 0x5418
  103.  
  104. #TIOCM_LE = hasattr(TERMIOS, 'TIOCM_LE') and TERMIOS.TIOCM_LE or 0x001
  105. TIOCM_DTR = hasattr(TERMIOS, 'TIOCM_DTR') and TERMIOS.TIOCM_DTR or 0x002
  106. TIOCM_RTS = hasattr(TERMIOS, 'TIOCM_RTS') and TERMIOS.TIOCM_RTS or 0x004
  107. #TIOCM_ST = hasattr(TERMIOS, 'TIOCM_ST') and TERMIOS.TIOCM_ST or 0x008
  108. #TIOCM_SR = hasattr(TERMIOS, 'TIOCM_SR') and TERMIOS.TIOCM_SR or 0x010
  109.  
  110. TIOCM_CTS = hasattr(TERMIOS, 'TIOCM_CTS') and TERMIOS.TIOCM_CTS or 0x020
  111. TIOCM_CAR = hasattr(TERMIOS, 'TIOCM_CAR') and TERMIOS.TIOCM_CAR or 0x040
  112. TIOCM_RNG = hasattr(TERMIOS, 'TIOCM_RNG') and TERMIOS.TIOCM_RNG or 0x080
  113. TIOCM_DSR = hasattr(TERMIOS, 'TIOCM_DSR') and TERMIOS.TIOCM_DSR or 0x100
  114. TIOCM_CD  = hasattr(TERMIOS, 'TIOCM_CD') and TERMIOS.TIOCM_CD or TIOCM_CAR
  115. TIOCM_RI  = hasattr(TERMIOS, 'TIOCM_RI') and TERMIOS.TIOCM_RI or TIOCM_RNG
  116. #TIOCM_OUT1 = hasattr(TERMIOS, 'TIOCM_OUT1') and TERMIOS.TIOCM_OUT1 or 0x2000
  117. #TIOCM_OUT2 = hasattr(TERMIOS, 'TIOCM_OUT2') and TERMIOS.TIOCM_OUT2 or 0x4000
  118. TIOCINQ   = hasattr(TERMIOS, 'FIONREAD') and TERMIOS.FIONREAD or 0x541B
  119.  
  120. TIOCM_zero_str = struct.pack('I', 0)
  121. TIOCM_RTS_str = struct.pack('I', TIOCM_RTS)
  122. TIOCM_DTR_str = struct.pack('I', TIOCM_DTR)
  123.  
  124. baudrate_constants = {
  125.     0:       0000000,  # hang up
  126.     50:      0000001,
  127.     75:      0000002,
  128.     110:     0000003,
  129.     134:     0000004,
  130.     150:     0000005,
  131.     200:     0000006,
  132.     300:     0000007,
  133.     600:     0000010,
  134.     1200:    0000011,
  135.     1800:    0000012,
  136.     2400:    0000013,
  137.     4800:    0000014,
  138.     9600:    0000015,
  139.     19200:   0000016,
  140.     38400:   0000017,
  141.     57600:   0010001,
  142.     115200:  0010002,
  143.     230400:  0010003,
  144.     460800:  0010004,
  145.     500000:  0010005,
  146.     576000:  0010006,
  147.     921600:  0010007,
  148.     1000000: 0010010,
  149.     1152000: 0010011,
  150.     1500000: 0010012,
  151.     2000000: 0010013,
  152.     2500000: 0010014,
  153.     3000000: 0010015,
  154.     3500000: 0010016,
  155.     4000000: 0010017
  156. }
  157.     
  158.  
  159. class Serial(SerialBase):
  160.     """Serial port class POSIX implementation. Serial port configuration is 
  161.     done with termios and fcntl. Runs on Linux and many other Un*x like
  162.     systems."""
  163.  
  164.     def open(self):
  165.         """Open port with current settings. This may throw a SerialException
  166.            if the port cannot be opened."""
  167.         if self._port is None:
  168.             raise SerialException("Port must be configured before it can be used.")
  169.         self.fd = None
  170.         #open
  171.         try:
  172.             self.fd = os.open(self.portstr, os.O_RDWR|os.O_NOCTTY|os.O_NONBLOCK)
  173.         except Exception, msg:
  174.             self.fd = None
  175.             raise SerialException("could not open port %s: %s" % (self._port, msg))
  176.         #~ fcntl.fcntl(self.fd, FCNTL.F_SETFL, 0)  #set blocking
  177.         
  178.         try:
  179.             self._reconfigurePort()
  180.         except:
  181.             os.close(self.fd)
  182.             self.fd = None
  183.         else:
  184.             self._isOpen = True
  185.         #~ self.flushInput()
  186.         
  187.         
  188.     def _reconfigurePort(self):
  189.         """Set communication parameters on opened port."""
  190.         if self.fd is None:
  191.             raise SerialException("Can only operate on a valid port handle")
  192.             
  193.         vmin = vtime = 0                #timeout is done via select
  194.         try:
  195.             iflag, oflag, cflag, lflag, ispeed, ospeed, cc = termios.tcgetattr(self.fd)
  196.         except termios.error, msg:      #if a port is nonexistent but has a /dev file, it'll fail here
  197.             raise SerialException("Could not configure port: %s" % msg)
  198.         #set up raw mode / no echo / binary
  199.         cflag |=  (TERMIOS.CLOCAL|TERMIOS.CREAD)
  200.         lflag &= ~(TERMIOS.ICANON|TERMIOS.ECHO|TERMIOS.ECHOE|TERMIOS.ECHOK|TERMIOS.ECHONL|
  201.                      TERMIOS.ISIG|TERMIOS.IEXTEN) #|TERMIOS.ECHOPRT
  202.         for flag in ('ECHOCTL', 'ECHOKE'): #netbsd workaround for Erk
  203.             if hasattr(TERMIOS, flag):
  204.                 lflag &= ~getattr(TERMIOS, flag)
  205.         
  206.         oflag &= ~(TERMIOS.OPOST)
  207.         iflag &= ~(TERMIOS.INLCR|TERMIOS.IGNCR|TERMIOS.ICRNL|TERMIOS.IGNBRK)
  208.         if hasattr(TERMIOS, 'IUCLC'):
  209.             iflag &= ~TERMIOS.IUCLC
  210.         if hasattr(TERMIOS, 'PARMRK'):
  211.             iflag &= ~TERMIOS.PARMRK
  212.         
  213.         #setup baudrate
  214.         try:
  215.             ispeed = ospeed = getattr(TERMIOS,'B%s' % (self._baudrate))
  216.         except AttributeError:
  217.             try:
  218.                 ispeed = ospeed = baudrate_constants[self._baudrate]
  219.             except KeyError:
  220.                 raise ValueError('Invalid baud rate: %r' % self._baudrate)
  221.         #setup char len
  222.         cflag &= ~TERMIOS.CSIZE
  223.         if self._bytesize == 8:
  224.             cflag |= TERMIOS.CS8
  225.         elif self._bytesize == 7:
  226.             cflag |= TERMIOS.CS7
  227.         elif self._bytesize == 6:
  228.             cflag |= TERMIOS.CS6
  229.         elif self._bytesize == 5:
  230.             cflag |= TERMIOS.CS5
  231.         else:
  232.             raise ValueError('Invalid char len: %r' % self._bytesize)
  233.         #setup stopbits
  234.         if self._stopbits == STOPBITS_ONE:
  235.             cflag &= ~(TERMIOS.CSTOPB)
  236.         elif self._stopbits == STOPBITS_TWO:
  237.             cflag |=  (TERMIOS.CSTOPB)
  238.         else:
  239.             raise ValueError('Invalid stopit specification: %r' % self._stopbits)
  240.         #setup parity
  241.         iflag &= ~(TERMIOS.INPCK|TERMIOS.ISTRIP)
  242.         if self._parity == PARITY_NONE:
  243.             cflag &= ~(TERMIOS.PARENB|TERMIOS.PARODD)
  244.         elif self._parity == PARITY_EVEN:
  245.             cflag &= ~(TERMIOS.PARODD)
  246.             cflag |=  (TERMIOS.PARENB)
  247.         elif self._parity == PARITY_ODD:
  248.             cflag |=  (TERMIOS.PARENB|TERMIOS.PARODD)
  249.         else:
  250.             raise ValueError('Invalid parity: %r' % self._parity)
  251.         #setup flow control
  252.         #xonxoff
  253.         if hasattr(TERMIOS, 'IXANY'):
  254.             if self._xonxoff:
  255.                 iflag |=  (TERMIOS.IXON|TERMIOS.IXOFF) #|TERMIOS.IXANY)
  256.             else:
  257.                 iflag &= ~(TERMIOS.IXON|TERMIOS.IXOFF|TERMIOS.IXANY)
  258.         else:
  259.             if self._xonxoff:
  260.                 iflag |=  (TERMIOS.IXON|TERMIOS.IXOFF)
  261.             else:
  262.                 iflag &= ~(TERMIOS.IXON|TERMIOS.IXOFF)
  263.         #rtscts
  264.         if hasattr(TERMIOS, 'CRTSCTS'):
  265.             if self._rtscts:
  266.                 cflag |=  (TERMIOS.CRTSCTS)
  267.             else:
  268.                 cflag &= ~(TERMIOS.CRTSCTS)
  269.         elif hasattr(TERMIOS, 'CNEW_RTSCTS'):   #try it with alternate constant name
  270.             if self._rtscts:
  271.                 cflag |=  (TERMIOS.CNEW_RTSCTS)
  272.             else:
  273.                 cflag &= ~(TERMIOS.CNEW_RTSCTS)
  274.         #XXX should there be a warning if setting up rtscts (and xonxoff etc) fails??
  275.         
  276.         #buffer
  277.         #vmin "minimal number of characters to be read. = for non blocking"
  278.         if vmin < 0 or vmin > 255:
  279.             raise ValueError('Invalid vmin: %r ' % vmin)
  280.         cc[TERMIOS.VMIN] = vmin
  281.         #vtime
  282.         if vtime < 0 or vtime > 255:
  283.             raise ValueError('Invalid vtime: %r' % vtime)
  284.         cc[TERMIOS.VTIME] = vtime
  285.         #activate settings
  286.         termios.tcsetattr(self.fd, TERMIOS.TCSANOW, [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
  287.  
  288.     def close(self):
  289.         """Close port"""
  290.         if self._isOpen:
  291.             if self.fd is not None:
  292.                 os.close(self.fd)
  293.                 self.fd = None
  294.             self._isOpen = False
  295.  
  296.     def makeDeviceName(self, port):
  297.         return device(port)
  298.  
  299.     #  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
  300.  
  301.     def inWaiting(self):
  302.         """Return the number of characters currently in the input buffer."""
  303.         #~ s = fcntl.ioctl(self.fd, TERMIOS.FIONREAD, TIOCM_zero_str)
  304.         s = fcntl.ioctl(self.fd, TIOCINQ, TIOCM_zero_str)
  305.         return struct.unpack('I',s)[0]
  306.  
  307.     def read(self, size=1):
  308.         """Read size bytes from the serial port. If a timeout is set it may
  309.            return less characters as requested. With no timeout it will block
  310.            until the requested number of bytes is read."""
  311.         if self.fd is None: raise portNotOpenError
  312.         read = ''
  313.         inp = None
  314.         if size > 0:
  315.             while len(read) < size:
  316.                 #print "\tread(): size",size, "have", len(read)    #debug
  317.                 ready,_,_ = select.select([self.fd],[],[], self._timeout)
  318.                 if not ready:
  319.                     break   #timeout
  320.                 buf = os.read(self.fd, size-len(read))
  321.                 read = read + buf
  322.                 if self._timeout >= 0 and not buf:
  323.                     break  #early abort on timeout
  324.         return read
  325.  
  326.     def write(self, data):
  327.         """Output the given string over the serial port."""
  328.         if self.fd is None: raise portNotOpenError
  329.         if not isinstance(data, str):
  330.             raise TypeError('expected str, got %s' % type(data))
  331.         t = len(data)
  332.         d = data
  333.         while t > 0:
  334.             try:
  335.                 if self._writeTimeout is not None and self._writeTimeout > 0:
  336.                     _,ready,_ = select.select([],[self.fd],[], self._writeTimeout)
  337.                     if not ready:
  338.                         raise writeTimeoutError
  339.                 n = os.write(self.fd, d)
  340.                 if self._writeTimeout is not None and self._writeTimeout > 0:
  341.                     _,ready,_ = select.select([],[self.fd],[], self._writeTimeout)
  342.                     if not ready:
  343.                         raise writeTimeoutError
  344.                 d = d[n:]
  345.                 t = t - n
  346.             except OSError,v:
  347.                 if v.errno != errno.EAGAIN:
  348.                     raise
  349.  
  350.     def flush(self):
  351.         """Flush of file like objects. In this case, wait until all data
  352.            is written."""
  353.         self.drainOutput()
  354.  
  355.     def flushInput(self):
  356.         """Clear input buffer, discarding all that is in the buffer."""
  357.         if self.fd is None:
  358.             raise portNotOpenError
  359.         termios.tcflush(self.fd, TERMIOS.TCIFLUSH)
  360.  
  361.     def flushOutput(self):
  362.         """Clear output buffer, aborting the current output and
  363.         discarding all that is in the buffer."""
  364.         if self.fd is None:
  365.             raise portNotOpenError
  366.         termios.tcflush(self.fd, TERMIOS.TCOFLUSH)
  367.  
  368.     def sendBreak(self, duration=0.25):
  369.         """Send break condition."""
  370.         if self.fd is None:
  371.             raise portNotOpenError
  372.         termios.tcsendbreak(self.fd, int(duration/0.25))
  373.  
  374.     def setRTS(self, level=1):
  375.         """Set terminal status line: Request To Send"""
  376.         if self.fd is None: raise portNotOpenError
  377.         if level:
  378.             fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_RTS_str)
  379.         else:
  380.             fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_RTS_str)
  381.  
  382.     def setDTR(self, level=1):
  383.         """Set terminal status line: Data Terminal Ready"""
  384.         if self.fd is None: raise portNotOpenError
  385.         if level:
  386.             fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_DTR_str)
  387.         else:
  388.             fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_DTR_str)
  389.  
  390.     def getCTS(self):
  391.         """Read terminal status line: Clear To Send"""
  392.         if self.fd is None: raise portNotOpenError
  393.         s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
  394.         return struct.unpack('I',s)[0] & TIOCM_CTS != 0
  395.  
  396.     def getDSR(self):
  397.         """Read terminal status line: Data Set Ready"""
  398.         if self.fd is None: raise portNotOpenError
  399.         s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
  400.         return struct.unpack('I',s)[0] & TIOCM_DSR != 0
  401.  
  402.     def getRI(self):
  403.         """Read terminal status line: Ring Indicator"""
  404.         if self.fd is None: raise portNotOpenError
  405.         s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
  406.         return struct.unpack('I',s)[0] & TIOCM_RI != 0
  407.  
  408.     def getCD(self):
  409.         """Read terminal status line: Carrier Detect"""
  410.         if self.fd is None: raise portNotOpenError
  411.         s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
  412.         return struct.unpack('I',s)[0] & TIOCM_CD != 0
  413.  
  414.     # - - platform specific - - - -
  415.  
  416.     def drainOutput(self):
  417.         """internal - not portable!"""
  418.         if self.fd is None: raise portNotOpenError
  419.         termios.tcdrain(self.fd)
  420.  
  421.     def nonblocking(self):
  422.         """internal - not portable!"""
  423.         if self.fd is None:
  424.             raise portNotOpenError
  425.         fcntl.fcntl(self.fd, FCNTL.F_SETFL, FCNTL.O_NONBLOCK)
  426.  
  427.     def fileno(self):
  428.         """For easier of the serial port instance with select.
  429.            WARNING: this function is not portable to different platforms!"""
  430.         if self.fd is None: raise portNotOpenError
  431.         return self.fd
  432.  
  433. if __name__ == '__main__':
  434.     s = Serial(0,
  435.                  baudrate=19200,        #baudrate
  436.                  bytesize=EIGHTBITS,    #number of databits
  437.                  parity=PARITY_EVEN,    #enable parity checking
  438.                  stopbits=STOPBITS_ONE, #number of stopbits
  439.                  timeout=3,             #set a timeout value, None for waiting forever
  440.                  xonxoff=0,             #enable software flow control
  441.                  rtscts=0,              #enable RTS/CTS flow control
  442.                )
  443.     s.setRTS(1)
  444.     s.setDTR(1)
  445.     s.flushInput()
  446.     s.flushOutput()
  447.     s.write('hello')
  448.     print repr(s.read(5))
  449.     print s.inWaiting()
  450.     del s
  451.  
  452.